<!--
 * @Author: lp
 * @Date: 2022-02-08 11:21:01
 * @LastEditTime: 2022-05-18 10:45:49
 * @LastEditors: lp 654528967@qq.com
 * @Description: 自定义输入组件
 type 表示输入框类型
 option 表示配置 参考el各组件attrs，除了少部分值，其他的都直接传递到了相对应的组件attrs上面
 特殊的 atrrs :
	一、select : dictInfo 字典配置

 dictInfo 的配置:
	dict:string|array 传入string应该是store/modules/dict 下的枚举类型DictDirection;如果是数组，则表示会采用此作为源数据展示
	dictLabel:string 默认值为dictLabel 表示字典要展示的值
	dictValue:string 默认值为dictValue 表示字典要设定的值
 * @FilePath: \nien-vue3-admin\src\components\customInput\index.vue
-->
<script lang="tsx">
import { defineComponent, withDirectives, resolveDirective, DirectiveArguments, Directive } from 'vue'
import { toHumpName, praseStrEmpty } from '@/utils/index'
import useDicts, { DictDirection, dictInfo } from '@/store/modules/dicts'
// default export referencing variable declaration: ok
const dicts = useDicts()
export default defineComponent({
  props: {
    option: {
      type: Object,
      default: () => ({}),
    },
    type: {
      type: String,
      default: 'input',
    },
  },
  setup() {
    return { dicts }
  },
  data() {
    return {}
  },
  computed: {
    dictArr() {
      const dict = this.option?.dictInfo?.dict
      return Array.isArray(dict) ? this.option.dictInfo.dict : this.dicts[dict]
    },
    nType() {
      // 转驼峰命名
      const str = toHumpName(this.type).toLocaleLowerCase()
      return str
    },
  },
  created() {
    if (this.option && this.option.dictInfo && this.option.dictInfo.dict in DictDirection && !Array.isArray(this.option.dictInfo.dict)) this.dicts.setDicts(this.option.dictInfo.dict)
  },
  render() {
    let component = null
    const {
      $attrs,
      option: { directives, dictInfo: componentDictInfo, ...OtherOpt },
    } = this
    const data = {
      ...$attrs,
      // 直接加在组件上的attrs
      ...OtherOpt,
    }
    let dict = null,
      dictLabel = null,
      dictValue = null
    if (componentDictInfo) {
      ({ dict, dictValue, dictLabel } = componentDictInfo)
      const dictItem = dictInfo[dict]
      if ((dictItem && typeof dictItem.url === 'function') || Array.isArray(dict)) {
        const setDict = (feild, key) => {
          if (praseStrEmpty(feild) === '') {
            if (praseStrEmpty(dictItem[key]) === '') throw new Error(`${ DictDirection[dict] }字典未设置dictValue`)
            return dictItem[key]
          } 
          return feild
        }
        dictValue = setDict(dictValue, 'dictValue')
        dictLabel = setDict(dictLabel, 'dictLabel')
      } else {
        dictValue = 'dictValue'
        dictLabel = 'dictLabel'
      }
    }

    if (this.nType === 'input') {
      component = <el-input {...{ placeholder: '请输入', ...data }} />
    } else if (this.nType === 'select') {
      component = (
        <el-select {...{ style: 'width:100%;', placeholder: '请选择', filterable: true, ...data }}>
          {this.dictArr.map((el, index) => (
            <el-option label={el[dictLabel]} value={el[dictValue]} key={index}></el-option>
          ))}
        </el-select>
      )
    } else if (this.nType === 'selectv2') {
      component = (
        <el-select-v2
          {...{ placeholder: '请选择', filterable: true, ...data }}
          style="width:100%;"
          options={this.dictArr.map((el) => ({
            label: el[dictLabel],
            value: el[dictValue],
          }))}
        />
      )
    } else if (this.nType === 'inputnumber') {
      component = <el-input-number {...{ placeholder: '请输入', ...data }} />
    } else if (this.nType === 'radio') {
      // 单选框
      component = (
        <el-radio-group {...data}>
          {this.dictArr.map((el, index) => (
            <el-radio key={index} label={el[dictValue]}>
              {el[dictLabel]}
            </el-radio>
          ))}
        </el-radio-group>
      )
    } else if (this.nType === 'checkbox') {
      // 复选框
      component = (
        <el-checkbox-group {...data}>
          {this.dictArr.map((el, index) => (
            <el-checkbox key={index} label={el[dictValue]}>
              {el[dictLabel]}
            </el-checkbox>
          ))}
        </el-checkbox-group>
      )
    } else if (this.nType === 'cascader') {
      // 级联选择器
      component = <el-cascader {...{ placeholder: '请选择', ...data }} />
    } else if (this.nType === 'datepicker') {
      // 日期选择器
      component = <el-date-picker {...{ placeholder: '请选择', ...data }} />
    } else if (this.nType === 'timeselect') {
      // 时间选择
      component = <el-time-select {...{ placeholder: '请选择', ...data }} />
    } else if (this.nType === 'timepicker') {
      // 时间选择器
      component = <el-time-picker {...{ placeholder: '请选择', ...data }} />
    } else {
      component = <div>组件未定义</div>
    }
    // 指令相关
    let dir: DirectiveArguments = []
    if (Array.isArray(directives) && directives.length > 0) {
      dir = directives.map((el: [any]): [Directive] => {
        const [dir, ...other] = el
				dir as string
				const resolvedDir = resolveDirective(dir)
				if (!resolvedDir) throw new Error('指令解析错误')
				return [resolvedDir, ...other]
      })
    }
    if (dir.length > 0) {
      return withDirectives(component, dir)
    }
    return component
  },
})
</script>
